package com.koko.service.Impl;

import com.koko.constant.DefaultDataConstant;
import com.koko.constant.MessageConstant;
import com.koko.context.BaseContext;
import com.koko.exception.AccountAlredyExistException;
import com.koko.exception.AccountNotFoundException;
import com.koko.exception.InsufficientWalletBalanceException;
import com.koko.exception.PasswordErrorException;
import com.koko.feign.OrderFeignService;
import com.koko.mapper.FriendsMapper;
import com.koko.mapper.UserMapper;
import com.koko.order.vo.UserAddGameByOrderVO;
import com.koko.properties.HttpParamsProperties;
import com.koko.properties.HttpPathProperties;
import com.koko.result.Result;
import com.koko.service.UserGameService;
import com.koko.service.UserService;
import com.koko.user.dto.RecoverPasswordDTO;
import com.koko.user.dto.RegisterDTO;
import com.koko.user.entity.User;
import com.koko.user.entity.UserGame;
import com.koko.user.vo.UserVO;
import com.koko.utils.Base64Util;
import com.koko.utils.HttpUrlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    @Value("${koko.urlPrefix}")
    private String baseUrl;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private FriendsMapper friendsMapper;
    @Autowired
    private OrderFeignService orderFeignService;
    @Autowired
    private UserGameService userGameService;

    /**
     * 获取用户信息
     * @return
     */
    @Override
    public UserVO getUserInfo() {
        Long currentUserId = BaseContext.getCurrentId();
        User user = userMapper.getById(currentUserId);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    /**
     * 密码登录
     * @param usernameOrEmail
     * @param password
     * @return
     */
    @Override
    public UserVO login(String usernameOrEmail, String password) {
        // 1. 对密码进行md5加密
        String encryptionPassword = DigestUtils.md5DigestAsHex(password.getBytes());
        // 2. 根据提交的用户名查询数据库
        User userInDB = userMapper.getByUsernameOrEmail(usernameOrEmail);
        // 3. 处理各种异常
        if (userInDB == null) {
            // 账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }
        if (!encryptionPassword.equals(userInDB.getPassword())) {
            // 密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userInDB, userVO);
        return userVO;
    }

    /**
     * 通过邮箱获取用户信息
     * @param email
     * @return
     */
    @Override
    public UserVO getUserInfoByEmail(String email) {
        User user = userMapper.getByUsernameOrEmail(email);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    /**
     * 注册
     * @param registerDTO
     */
    @Override
    public void register(RegisterDTO registerDTO) {
        // 1. 查询数据库中是否存在相同用户
         Integer count = userMapper.checkIfExists(registerDTO);
        if (count > 0) {
            // 用户已存在
            throw new AccountAlredyExistException(MessageConstant.ACCOUNT_ALREADY_EXIST);
        }
        // 2. 封装数据
        String password = DigestUtils.md5DigestAsHex(registerDTO.getPassword().getBytes());
        User user = new User();
        BeanUtils.copyProperties(registerDTO, user);
        if (registerDTO.getNickname() == null || registerDTO.getNickname().isEmpty()) {
            // 用户没有设置昵称，将username赋值给nickname
            user.setNickname(registerDTO.getUsername());
        }
        user.setPassword(password);
        // 设置默认数据
        user.setBirthDate(DefaultDataConstant.DEFAULT_BIRTH_DATE);
        user.setIntroduction(DefaultDataConstant.DEFAULT_INTRODUCTION);
        user.setWallet(DefaultDataConstant.DEFAULT_WALLET);
        user.setAvatar(DefaultDataConstant.DEFAULT_AVATAR);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        // 3. 插入数据
        userMapper.insert(user);
    }

    /**
     * 获取用户好友列表
     * @return
     */
    @Override
    public List<UserVO> getFriendsList(String usernameOrNickname) {
        // 获取好友id
        /*List<Long> friendsIdList = friendsMapper.getUserFriendsByCurrentId(BaseContext.getCurrentId());
        List<UserVO> list = friendsIdList.stream().map((id) -> {
            UserVO friendVO = new UserVO();
            User friend = userMapper.getById(id);
            BeanUtils.copyProperties(friend, friendVO);
            friendVO.setAvatar(Base64Util.convertImageToBase64(basePath + friend.getAvatar()));
            friendVO.setWallet(null);
            friendVO.setEmail(null);
            return friendVO;
        }).collect(Collectors.toList());*/
        List<User> friendsList = userMapper.getFriendsListByUserId(usernameOrNickname, BaseContext.getCurrentId());
        List<UserVO> list = friendsList.stream().map((item) -> {
            UserVO friendVO = new UserVO();
            BeanUtils.copyProperties(item, friendVO);
            String url = HttpUrlUtil.imageRequestUrlEncapsulate(
                    baseUrl + HttpPathProperties.USER_AVATAR_DOWNLOAD,
                    HttpParamsProperties.USER_AVATAR_NAME + item.getAvatar());
            friendVO.setAvatar(url);
            friendVO.setWallet(null);
            friendVO.setEmail(null);
            return friendVO;
        }).collect(Collectors.toList());
        return list;
    }

    /**
     * 通过id获取用户信息
     * @param id
     * @return
     */
    @Override
    public UserVO getUserById(Long id) {
        User user = userMapper.getById(id);
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    /**
     * 支付接口
     * @param toPay
     */
    @Override
    public void pay(BigDecimal toPay) {
        // 1. 获取数据库中的数据
        User userInDB = userMapper.getById(BaseContext.getCurrentId());
        // 2. 扣钱
        BigDecimal newWallet = userInDB.getWallet().subtract(toPay);
        if (newWallet.signum() == -1) {
            // 2.1 负数，余额不足
            throw new InsufficientWalletBalanceException(MessageConstant.INSUFFICIENT_WALLET_BALANCE);
        }
        // 3. 封装扣款后的数据
        User userAfterPay = new User();
        userAfterPay.setId(userInDB.getId());
        userAfterPay.setWallet(newWallet);
        // 4. 写入数据库
        userMapper.update(userAfterPay);
    }

    /**
     * 通过订单获取游戏
     * @param
     */
    @Override
    public void getGamesFromOrder(Long orderId) {
        // 1. 通过Feign获取游戏列表
        Result<List<UserAddGameByOrderVO>> result = orderFeignService.getGameIdsOnOrderByOrderId(orderId);
        for (UserAddGameByOrderVO UserAddGameByOrder : result.getData()) {
            UserGame userGame = new UserGame();
            // 2. 封装数据
            userGame.setUserId(UserAddGameByOrder.getUserId());
            userGame.setGameId(UserAddGameByOrder.getGameId());
            userGame.setCreateTime(LocalDateTime.now());
            // 3. 写入用户游戏关系表
            userGameService.addGameForUser(userGame);
        }
    }

    /**
     * 修改密码
     * @param recoverPasswordDTO
     */
    @Override
    public void recoverPassword(RecoverPasswordDTO recoverPasswordDTO) {
        // 1. 密码加密
        String password = DigestUtils.md5DigestAsHex(recoverPasswordDTO.getRePassword().getBytes());
        // 2. 获取数据库中的用户
        User userInDB = userMapper.getByUsernameOrEmail(recoverPasswordDTO.getEmail());
        // 3. 修改密码
        userInDB.setPassword(password);
        // 4. 写入数据库
        userMapper.update(userInDB);
    }
}
